home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / prof / sun4c.md / _mcount.c next >
C/C++ Source or Header  |  1991-05-24  |  5KB  |  197 lines

  1. /* 
  2.  * _mcount.c --
  3.  *
  4.  *    This is the code for the routine mcount.  mcount is the routine
  5.  *    called at the beginning of each procedure if it the code has
  6.  *    been compiled with the -p option to cc.
  7.  *
  8.  *    NB: The compiler compiles this procedure into something called
  9.  *    "_mcount" which we massage back into "mcount" (see the Makefile).
  10.  *
  11.  * Copyright 1985 Regents of the University of California
  12.  * All rights reserved.
  13.  */
  14.  
  15. #ifndef lint
  16. static char rcsid[] = "$Header: /sprite/src/kernel/prof/sun4.md/RCS/_mcount.c,v 1.4 90/11/08 10:35:07 rab Exp $ SPRITE (Berkeley)";
  17. #endif
  18.  
  19. #include <sprite.h>
  20. #include <prof.h>
  21. #include <profInt.h>
  22. #include <sync.h>
  23. #include <sys.h>
  24. #include <dbg.h>
  25. #include <stdio.h>
  26.  
  27. #define MCOUNT
  28.  
  29. /*
  30.  * Boolean to prevent recursion in mcount.  This only works
  31.  * on a uniprocessor.  This is needed in case we call printf
  32.  * or a Sync_ routine from within mcount and those routines
  33.  * have been instrumented with calls to mcount.
  34.  */
  35. static Boolean inMcount = FALSE;
  36.  
  37. /*
  38.  * There is a critical section when mcount does a pseudo-alloc
  39.  * of the storage for its arcs.
  40.  */
  41. #ifdef MCOUNT 
  42. #ifndef lint
  43. static Sync_Semaphore    mcountMutex = Sync_SemInitStatic("mcountMutex");
  44. #endif
  45. #endif
  46.  
  47.  
  48. /*
  49.  *----------------------------------------------------------------------
  50.  *
  51.  * mcount --
  52.  *
  53.  *    A call to this routine is inserted by the compiler at the
  54.  *    beginning of every routine. (Use the -p option to cc.)
  55.  *    This looks up the call stack a bit to determine which arc
  56.  *    of the call graph is being executed.  A call graph arc represents
  57.  *    one routine calling another.  The routine with the call to mcount
  58.  *    is the callee of the arc, its caller (mcount's "grandparent")
  59.  *    is the caller of the arc.  An execution count is kept for each
  60.  *    arc.  The counts are dumped out and analyzed by the gprof program.
  61.  *
  62.  * Results:
  63.  *    None.
  64.  *
  65.  * Side effects:
  66.  *    Increment a counter corresponding to the call graph arc.
  67.  *
  68.  *----------------------------------------------------------------------
  69.  */
  70. void
  71. __mcount(callerPC, calleePC)
  72.     unsigned int callerPC;    /* PC of instr. that called mcount's caller */
  73.     unsigned int calleePC;    /* PC of instr. that called mcount */
  74. {
  75. #ifdef MCOUNT
  76.     register unsigned int instructionNumber;    /* Index into profArcIndex */
  77.     register ProfRawArc *arcPtr;    /* Pointer to arc data storage */
  78.  
  79.     if (!profEnabled) {
  80.     return;
  81.     }
  82.  
  83.     if (inMcount) {
  84.     return;
  85.     } else {
  86.     inMcount = TRUE;
  87.     }
  88.  
  89.     /*
  90.      * Use the PC of the caller as an index into the
  91.      * index of stored arcs.  There should only be one call instruction
  92.      * that corresponds to the index.
  93.      *
  94.      * Go from PC to instruction number by subracting off the base
  95.      * PC and dividing by the instruction size (4 bytes).
  96.      */
  97.  
  98.     if (callerPC < (unsigned int)&spriteStart) {
  99.     /*
  100.      * The PC from the caller's frame is bad. This happens when a 
  101.      * new process is started. 
  102.      */
  103.     goto exit;
  104.     }
  105.  
  106.     instructionNumber = 
  107.         (callerPC - (unsigned int) &spriteStart) >> PROF_ARC_SHIFT;
  108.     if (instructionNumber > profArcIndexSize) {
  109.     printf("_mcount: PC %x: Index (%d) exceeds bounds (%d)\n",
  110.           callerPC, instructionNumber, profArcIndexSize);
  111.     goto exit;
  112.     }
  113.  
  114.     /*
  115.      * Check to see if arcPtr equals an unused value (which is 0 because
  116.      * profArcIndex is initialized with bzero in Prof_Start).
  117.      */
  118.  
  119.     arcPtr = profArcIndex[instructionNumber];
  120.     if (arcPtr == (ProfRawArc *) 0) {
  121.  
  122. #ifdef DEBUG
  123.     printf("mcount: 1 callerPC = %x(%d), calleePC = %x\n",
  124.                 callerPC, instructionNumber, calleePC);
  125.     /* DBG_CALL; */
  126. #endif
  127.  
  128.     /*
  129.      * First time call graph arc has been traversed.  Allocate arc
  130.      * storage from the arcList and initialize it.  This is locked
  131.      * to prevent the scheduler from interrupting the allocation
  132.      * and initialization.
  133.      */
  134.  
  135.     if (profArcListFreePtr >= profArcListEndPtr) {
  136.         profEnabled = FALSE;
  137.         printf("_mcount: No more arcs, stopping profiling\n");
  138.     } else {
  139.  
  140.         MASTER_LOCK(&mcountMutex);
  141.         Sync_SemRegister(&mcountMutex);
  142.  
  143.         arcPtr = profArcListFreePtr;
  144.         profArcListFreePtr++;
  145.         profArcIndex[instructionNumber] = arcPtr;
  146.         arcPtr->calleePC = calleePC;
  147.         arcPtr->count    = 1;
  148.         arcPtr->link     = (ProfRawArc *)NIL;
  149.  
  150.         MASTER_UNLOCK(&mcountMutex);
  151.     }
  152.     goto exit;
  153.     }
  154.  
  155.     while (arcPtr->calleePC != calleePC) {
  156.     /*
  157.      * Loop through the list of callee's for this caller.
  158.      */
  159.  
  160.     if (arcPtr->link == (ProfRawArc *)NIL) {
  161.  
  162.         /*
  163.          *  Allocate, link, and initialize another arc storage unit.
  164.          */
  165. #ifdef DEBUG
  166.         printf("mcount 2 callerPC = %x(%d), calleePC = %x\n",
  167.             callerPC, instructionNumber, calleePC);
  168.     /* DBG_CALL; */
  169. #endif
  170.  
  171.         if (profArcListFreePtr >= profArcListEndPtr) {
  172.         printf("_mcount: No more arcs\n");
  173.         } else {
  174.         MASTER_LOCK(&mcountMutex);
  175.  
  176.         arcPtr->link = profArcListFreePtr;
  177.         profArcListFreePtr++;
  178.  
  179.         arcPtr = arcPtr->link;
  180.         arcPtr->calleePC    = calleePC;
  181.         arcPtr->count        = 1;
  182.         arcPtr->link        = (ProfRawArc *) NIL;
  183.  
  184.         MASTER_UNLOCK(&mcountMutex);
  185.         }
  186.         goto exit;
  187.     }
  188.     arcPtr = arcPtr->link;
  189.     }
  190.     arcPtr->count++;
  191.  
  192. exit:
  193. #endif /* MCOUNT */
  194.     inMcount = FALSE;
  195.     return;
  196. }
  197.